#pragma once
#include "macros.h"
#include "kernel_operator.h"
#include "limits"

static constexpr uint32_t STRIDE_LIMIT = 65536;

static constexpr uint32_t BYTE_PER_FRACTAL = 512;
static constexpr uint32_t BYTE_PER_C0 = 32;
static constexpr uint32_t C0_NUM_PER_FRACTAL = 16;

template <uint32_t ALIGN, typename T>
ACTLASS_HOST_DEVICE T RoundUp(const T val) {
    T align = ALIGN;
    return (val + align - 1) / align * align;
}

template <typename T>
ACTLASS_HOST_DEVICE T RoundUp(const T val, const T align) {
    if (align == 0) {
        return 0;
    } else {
        return (val + align - 1) / align * align;
    }
}

template <uint32_t ALIGN, typename T>
ACTLASS_HOST_DEVICE constexpr T RoundDown(const T val) {
    T align = ALIGN;
    return val / align * align;
}

template <typename T>
ACTLASS_HOST_DEVICE constexpr T RoundDown(const T val, const T align) {
    if (align == 0) {
        return 0;
    }
    return val / align * align;
}

template <uint32_t DIVISOP, typename T>
ACTLASS_HOST_DEVICE T CeilDiv(const T dividend) {
    T divisor = DIVISOP;
    return (dividend + divisor - 1) / divisor;
}

template <typename T>
constexpr T T_MAX = std::numeric_limits<T>::max();

template <typename T>
ACTLASS_HOST_DEVICE T CeilDiv(const T dividend, const T divisor) {
    if (divisor == 0) {
        return T_MAX<T>;
    } else {
        return (dividend + divisor - 1) / divisor;
    }
}